package org.opens.lambda.collector;

import java.util.*;
import java.util.function.BiConsumer;
import java.util.function.BinaryOperator;
import java.util.function.Function;
import java.util.function.Supplier;
import java.util.stream.Collector;

public class MyToListCollector<T> implements Collector<T, List<T>, List<T>> {

    private void log(final String log) {
        System.out.println(Thread.currentThread().getName() + "-" + log);
    }

    @Override
    public Supplier<List<T>> supplier() {
        log("进入-> supplier");
        return ArrayList::new;
    }

    /**
     * 说明:
     *      1. 该方法的原理是每次都会对流中的元素做这个操作.
     *      2. (x, y) -> x.add(y);这个函数中, x表示supplier()方法提供的容器对象, y表示stream中的元素.
     * @return  对流中每个元素做得操作
     */
    @Override
    public BiConsumer<List<T>, T> accumulator() {
        log("进入-> accumulator");
        //return (x, y) -> x.add(y);
        //return List::add;
        return (x, y) -> {
            log("accumulator 的 method 执行一次, 操作对象为: " + y);
            x.add(y);
        };
    }

    /**
     * 说明:
     *      1. 这个是在多线程环境下使用fork join框架进行合并线程计算记过时调用的, 定义两个线程的结果合并规则.
     *          - 注意的是, 如果要使当前Collector具有多线程的能力, 需要在characteristics方法中添加Characteristics.CONCURRENT标记, 表示支持并行.
     */
    @Override
    public BinaryOperator<List<T>> combiner() {
        log("进入-> combiner");
        return (list1, list2) -> {
            log("accumulator 的 combiner 执行一次");
            list1.addAll(list2);
            return list1;
        };
    }

    /**
     * 说明:
     *      1. 在stream中的元素被accumulator方法处理完毕之后, 就会调用这个方法将结果集进行转换.
     *          - 也就是说, 可以再这里定义转换规则, 但是需要注意的是这个方法的返回值是由Collector<T, List<T>, List<T>>的第三个泛型参数决定的.
     */
    @Override
    public Function<List<T>, List<T>> finisher() {
        log("进入-> finisher");
        //原样返回
        return Function.identity();
    }

    @Override
    public Set<Characteristics> characteristics() {
        log("进入-> characteristics");
        //IDENTITY_FINISH表示是最终操作, CONCURRENT表示支持并行
        return Collections.unmodifiableSet(EnumSet.of(Characteristics.IDENTITY_FINISH, Characteristics.CONCURRENT));
    }

}
